﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.ResourceManagement.ResourceProviders;
using UnityEngine.UI;
using static UnityEngine.AddressableAssets.Addressables;

public class GameLaunch : MonoBehaviour {

    public Action<string> OnStatusTipHasChanged;
    public Action<float> OnDownloadPercentHasChanged;
    public Action<bool> OnDownloadHasResult;

    AsyncOperationHandle<GameObject> handle;
    GameObject obj;

    /// <summary>
    /// 自定义指定待更新检测的 Label 集合
    /// </summary>
    private List<string> mKeys = new List<string>() { "default" };

    public IEnumerator CheckUpdate() {
        bool isNeedUpdateCatalog = false;
        bool isNeedUpdateResources = false;

        // 初始化 Addressable
        var initHandle = Addressables.InitializeAsync();
        yield return initHandle;
        OnStatusTipHasChanged?.Invoke("开始检查更新");
        Debug.LogError("开始检查更新");

        // 检查本地 Catalog 是否为最新版本
        var checkHandle = Addressables.CheckForCatalogUpdates(false);
        yield return checkHandle;
        if (checkHandle.Status == AsyncOperationStatus.Succeeded) {
            OnDownloadPercentHasChanged?.Invoke(1);
            OnStatusTipHasChanged?.Invoke("目录检查完成");
            Debug.LogError("目录检查完成");
        }

        List<string> catalogs = checkHandle.Result;
        if (catalogs != null && catalogs.Count > 0) {
            OnStatusTipHasChanged?.Invoke("检测到目录需要更新");
            Debug.LogError("检测到 Catalogs 需要更新");
            isNeedUpdateCatalog = true;
        } else {
            OnStatusTipHasChanged?.Invoke("检测到目录已是最新");
            Debug.LogError("检测到 Catalogs 已是最新");
        }

        var sizeHandle = Addressables.GetDownloadSizeAsync(mKeys);
        if (sizeHandle.Result > 0) {
            Debug.LogError("检测到有更新资源包");
            OnStatusTipHasChanged?.Invoke("检测到有更新资源包");
            isNeedUpdateResources = true;
        } else {
            Debug.LogError("检测到没有资源更新");
            OnStatusTipHasChanged?.Invoke("检测到没有资源更新");
        }

        OnStatusTipHasChanged?.Invoke("准备进行下一步");

        if (isNeedUpdateCatalog || isNeedUpdateResources) {
            if (isNeedUpdateCatalog) {
                yield return UpdateCatalog(catalogs);
            }
            if (isNeedUpdateResources) {
                yield return UpdateResources();
            }
            OnDownloadHasResult?.Invoke(true);
        } else {
            //StartGame();
            Debug.LogError("开始游戏");
        }
    }

    private void Update() {
        if (Input.GetKeyDown(KeyCode.C)) {
            StartCoroutine(CheckUpdate());
        }
        if (Input.GetKeyDown(KeyCode.L)) {
            handle = Addressables.LoadAssetAsync<GameObject>("Image");
            handle.Completed += param => {
                if (param.Status == AsyncOperationStatus.Succeeded) {
                    Debug.LogError("预加载成功");
                } else {
                    Debug.LogError("预加载失败");
                }
                obj = param.Result;
            };
        }
        if (Input.GetKeyDown(KeyCode.R)) {
            ReleaseCache();
        }
        if (Input.GetKeyDown(KeyCode.Space)) {
            Instantiate(obj, new Vector2(UnityEngine.Random.Range(0, 400), UnityEngine.Random.Range(0, 400)), Quaternion.identity, GameObject.Find("Canvas").transform);
        }
    }

    private IEnumerator UpdateCatalog(List<string> catalogs) {
        var updateHandle = Addressables.UpdateCatalogs(catalogs, false);
        Debug.LogError("开始更新 Catalogs");
        yield return updateHandle;

        Addressables.Release(updateHandle);
    }

    private IEnumerator UpdateResources() {
        ReleaseCache();
        // 需更新大小 > 0，表示需要下载更新
        // 清理旧资源
        //var clearHandle = Addressables.ClearDependencyCacheAsync(mKeys, false);
        //yield return clearHandle;

        // 下载待更新资源
        var downloadHandle = Addressables.DownloadDependenciesAsync(mKeys, MergeMode.Union, false);
        Debug.LogError("开始更新资源");
        while (!downloadHandle.IsDone) {
            DownloadStatus downloadStatus = downloadHandle.GetDownloadStatus();
            OnDownloadPercentHasChanged?.Invoke(downloadStatus.Percent);
            OnStatusTipHasChanged?.Invoke($"下载进度: {downloadStatus.Percent * 100} %");
            Debug.LogError($"下载进度: {downloadStatus.Percent * 100} %");
            yield return null;
        }
        if (downloadHandle.Status == AsyncOperationStatus.Succeeded) {
            OnStatusTipHasChanged?.Invoke($"下载情况：{(downloadHandle.IsDone ? "完成" : "未完成")}");
            Debug.LogError($"下载情况：{(downloadHandle.IsDone ? "完成" : "未完成")}");
        } else {
            OnStatusTipHasChanged?.Invoke($"下载更新包失败");
            Debug.LogError($"下载更新包失败，错误内容：{downloadHandle.OperationException.Message}");
        }
        Addressables.Release(downloadHandle);
    }

    private void ReleaseCache() {
        try {
            Addressables.Release(handle);
            Debug.LogError("释放资源成功");
        } catch (Exception) {
            Debug.LogError("释放资源失败");
        }
    }

}
